/*============================================================================*/
/*  Copyright (C) 2009-2018,  INFRASTRUCTURE SOFTWARE CO.,LTD.
 *
 *  All rights reserved. This software is  property. Duplication
 *  or disclosure without  written authorization is prohibited.
 *
 *  file       <Can_Hw.c>
 *  brief      < >
 *
 *  <Compiler:     MCU:MPC5746C >
 *
 *  author     <yongxing.jia>
 *  date       <03-12-2018>
 */
/*============================================================================*/
#include "Can.h"
#include "CanIf_Cbk.h"
#include "TypeDef.h"
extern CanControllerStatusType CanControllerStatus[CAN_MAX_CONTROLLERS];
extern const Can_ConfigType *Can_ConfigPtr;

/*=======[I N T E R N A L   F U N C T I O N   D E C L A R A T I O N S]========*/

/* Get the start of a MB address, based on its index. */
#define Can_Hw_Get_MsgBuff_8Payload_Addr(CanReg, MsgBuffIdx)   ((uint32)(((CanReg)->RAMn) + (uint32)((MsgBuffIdx) << 2u)))

uint32 Can_Hw_Get_MsgBuff_16Payload_Addr(Can_RegType* Can_Reg, uint8 MsgBuffIdx)
{
	uint32 Mb_Addr = 0u;

	Mb_Addr = ((uint32)((Can_Reg->RAMn) + (uint32)((MsgBuffIdx) << 2u)) + (uint32)(MsgBuffIdx << 3u));
	if(MsgBuffIdx > 20u)
	{
		Mb_Addr += 8u;
	}
	if(MsgBuffIdx > 41u)
	{
		Mb_Addr += 8u;
	}

	return Mb_Addr;
}

#define Can_Hw_Get_MsgBuff_32Payload_Addr(CanReg, MsgBuffIdx) ((uint32)(((CanReg)->RAMn) + (uint32)((MsgBuffIdx) << 3u)) + (uint32)(MsgBuffIdx << 3u))

uint32 Can_Hw_Get_MsgBuff_64Payload_Addr(Can_RegType* Can_Reg, uint8 MsgBuffIdx)
{
	uint32 Mb_Addr = 0u;
	Mb_Addr = ((uint32)((Can_Reg->RAMn) + (uint32)((MsgBuffIdx) << 4u)) + (uint32)(MsgBuffIdx << 3u));
	if(MsgBuffIdx > 6u)
	{
	    Mb_Addr += 8u;
	}
	if(MsgBuffIdx > 13u)
	{
		Mb_Addr += 8u;
	}

	return Mb_Addr;
}

static uint8 Can_Hw_ComputeDLCValue(const Can_PduType* PduInfo)
{
    uint8 DLC_Value;

    if (PduInfo->length <= 8U)
    {
        DLC_Value = PduInfo->length;
    }
    else if ((PduInfo->length > 8U) && (PduInfo->length <= 12U))
    {
        DLC_Value = DRV_CAN_MB_DLC_12_BYTES;
    }
    else if ((PduInfo->length > 12U) && (PduInfo->length <= 16U))
    {
        DLC_Value = DRV_CAN_MB_DLC_16_BYTES;
    }
    else if ((PduInfo->length > 16U) && (PduInfo->length <= 20U))
    {
        DLC_Value = DRV_CAN_MB_DLC_20_BYTES;
    }
    else if ((PduInfo->length > 20U) && (PduInfo->length <= 24U))
    {
        DLC_Value = DRV_CAN_MB_DLC_24_BYTES;
    }
    else if ((PduInfo->length > 24U) && (PduInfo->length <= 32U))
    {
        DLC_Value = DRV_CAN_MB_DLC_32_BYTES;
    }
    else if ((PduInfo->length > 32U) && (PduInfo->length <= 48U))
    {
        DLC_Value = DRV_CAN_MB_DLC_48_BYTES;
    }
    else if ((PduInfo->length > 48U) && (PduInfo->length <= 64U))
    {
        DLC_Value = DRV_CAN_MB_DLC_64_BYTES;
    }
    else
    {
        /* The argument is not a valid payload size */
        DLC_Value = 0xFFU;
    }
    return DLC_Value;
}

static uint8 Can_Hw_ComputeLengthValue(uint8 dlcValue)
{
    uint8 ret;

    if (dlcValue <= 8U)
    {
        ret = dlcValue;
    }
    else
    {
        switch (dlcValue)
        {
			case DRV_CAN_MB_DLC_12_BYTES:
				ret = 12U;
				break;
			case DRV_CAN_MB_DLC_16_BYTES:
				ret = 16U;
				break;
			case DRV_CAN_MB_DLC_20_BYTES:
				ret = 20U;
				break;
			case DRV_CAN_MB_DLC_24_BYTES:
				ret = 24U;
				break;
			case DRV_CAN_MB_DLC_32_BYTES:
				ret = 32U;
				break;
			case DRV_CAN_MB_DLC_48_BYTES:
				ret = 48U;
				break;
			case DRV_CAN_MB_DLC_64_BYTES:
				ret = 64U;
				break;
			default:
				/* The argument is not a valid DLC size */
				ret = 0xFFU;
				break;
        }
    }
    return ret;
}


static void Can_Hw_Rx_Tx_Mb_Init
(
	uint8 Controller,
	uint8 Can_Controller_Mb_Index,
	uint32 Can_HardwareObject_Index,
	const Can_ConfigType* Config,
	Can_MBDirectionType Direction
)
{
	uint8 Msg_Code = 0u;
	Can_Hw_RegTypeRef Can_Reg = (Can_Hw_RegTypeRef)Config->CanController[Controller].CanControllerBaseAddr;
	Can_Hw_MbTypeRef Can_Mb = Obtain_Mb_Addr(Controller, Can_Reg, Can_Controller_Mb_Index);

	/* Make sure Can MB buffer config are clear */
	Can_Mb->CONFIG = 0u;

	if(Config->CanController[Controller].CanFD_Support == TRUE)
	{
		/* EDL=1: Extended Data Length for CAN FD */
		Can_Mb->CONFIG |= DRV_CAN_MB_EDL;

		if(Config->CanController[Controller].CanControllerBaudrateConfig->CanControllerFdBaudrateConfig.CanControllerTxBitRateSwitch == TRUE)
		{
			/* BRS = 1: Bit Rate Switch enabled */
			Can_Mb->CONFIG |= DRV_CAN_MB_BRS;
		}
		else
		{
			/* BRS = 1: Bit Rate Switch enabled */
			Can_Mb->CONFIG &= (~DRV_CAN_MB_BRS);
		}
	}
	else
	{
		/* BRS = 0: Bit Rate Switch disabled */
		Can_Mb->CONFIG &= ~(DRV_CAN_MB_BRS | DRV_CAN_MB_EDL);
	}

	if(Config->Can_HardwareObject[Can_HardwareObject_Index].CanIdType == CAN_ID_TYPE_STANDARD)
	{
		/* Frame format is standard */
		/* Dominant is not a valid value for transmission in Extended Format frames */
		Can_Mb->CONFIG &= ~(DRV_CAN_MB_IDE | DRV_CAN_MB_SRR);
        if(Config->Can_HardwareObject[Can_HardwareObject_Index].CanHandleType == CAN_HANDLE_TYPE_BASIC)
        {
        	/* Config the Rx ID-mask for Basic CAN */
		    Can_Reg->RXIMR[Can_Controller_Mb_Index] = ((Config->Can_HardwareObject[Can_HardwareObject_Index].CanFilterMask) & 0x7ffu ) << 18u;
        }
        else if(Config->Can_HardwareObject[Can_HardwareObject_Index].CanHandleType == CAN_HANDLE_TYPE_FULL)
        {
        	/* Config the Rx ID-mask for Full CAN  */
        	Can_Reg->RXIMR[Can_Controller_Mb_Index] = 0x7ffu << 18u;
        }
        else
        {
        	/* Do Nothing */
        }

		Can_Mb->ID = Config->Can_HardwareObject[Can_HardwareObject_Index].CanIdValue << 18u;
	}
	else if(Config->Can_HardwareObject[Can_HardwareObject_Index].CanIdType == CAN_ID_TYPE_EXTENDED)
	{
		/* Set IDE: Frame format is extended. */
		Can_Mb->CONFIG |= DRV_CAN_MB_IDE;
		/* Dominant is not a valid value for transmission in Extended Format frames */
		Can_Mb->CONFIG &= ~DRV_CAN_MB_SRR;
		if(Config->Can_HardwareObject[Can_HardwareObject_Index].CanHandleType == CAN_HANDLE_TYPE_BASIC)
		{
			/* Config the Rx ID-mask for Basic CAN */
			Can_Reg->RXIMR[Can_Controller_Mb_Index] = Config->Can_HardwareObject[Can_HardwareObject_Index].CanFilterMask;
		}
		else if(Config->Can_HardwareObject[Can_HardwareObject_Index].CanHandleType == CAN_HANDLE_TYPE_FULL)
		{
			/* Config the Rx ID-mask for Full CAN  */
			Can_Reg->RXIMR[Can_Controller_Mb_Index] = 0x1fffffffu;
		}
		else
		{
			/* Do Nothing */
		}

		Can_Mb->ID = Config->Can_HardwareObject[Can_HardwareObject_Index].CanIdValue;
	}
	else
	{
		/* Do nothing */
	}

	/* Set MB CODE for Receive Message. */
	if(Direction == RX)
	{
		Msg_Code = CAN_RX_EMPTY;
	}
	else
	{
		Msg_Code = CAN_TX_INACTIVE;
	}

	Can_Mb->CONFIG |= (Msg_Code << 24u);

}



Can_Hw_MbTypeRef Obtain_Mb_Addr(uint8 Controller, Can_Hw_RegTypeRef Can_Reg, uint8 Can_Controller_Mb_Index)
{
	Can_Hw_MbTypeRef Can_Mb = NULL_PTR;

	switch(Can_ConfigPtr->CanController[Controller].CanControllerPayload)
	{
		case CAN_8_BYTES_PAYLOAD:
			Can_Mb = (Can_Hw_MbTypeRef)Can_Hw_Get_MsgBuff_8Payload_Addr(Can_Reg, Can_Controller_Mb_Index);
			break;
		case CAN_16_BYTES_PAYLOAD:
			Can_Mb = (Can_Hw_MbTypeRef)Can_Hw_Get_MsgBuff_16Payload_Addr(Can_Reg, Can_Controller_Mb_Index);
			break;
		case CAN_32_BYTES_PAYLOAD:
			Can_Mb = (Can_Hw_MbTypeRef)Can_Hw_Get_MsgBuff_32Payload_Addr(Can_Reg, Can_Controller_Mb_Index);
			break;
		case CAN_64_BYTES_PAYLOAD:
			Can_Mb = (Can_Hw_MbTypeRef)Can_Hw_Get_MsgBuff_64Payload_Addr(Can_Reg, Can_Controller_Mb_Index);
			break;
		default:
			break;
	}

	return Can_Mb;
}

/******************************************************************************/
/*
 * Brief               <This function This function enter freeze mode>
 * Param-Name[in]      <None>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
void Can_Hw_EnterFreezeMode(Can_RegType* Can_Reg)
{
	/* Enabled to enter Freeze Mode */
    /* Enters Freeze Mode if the FRZ bit is asserted */
	Can_Reg->MCR |= (uint32)(DRV_CAN_MCR_FRZ + DRV_CAN_MCR_HALT);

	/* Wait FlexCAN Enters Freeze Mode */
	while ((Can_Reg->MCR & DRV_CAN_MCR_FRZACK) == 0u){};
}
/******************************************************************************/
/*
 * Brief               <This function exit freeze mode>
 * Param-Name[in]      <None>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
void Can_Hw_ExitFreezeMode(Can_RegType* Can_Reg)
{
    /* Not enabled to enter Freeze Mode */
    /* No Freeze Mode request */
	Can_Reg->MCR &= (uint32)(~(DRV_CAN_MCR_FRZ + DRV_CAN_MCR_HALT));

	/* Wait FlexCAN not in Freeze Mode */
	while (((Can_Reg)->MCR & DRV_CAN_MCR_FRZACK) != 0u){};
}

void Can_Hw_ControllerInit(const Can_ConfigType* Config)
{
	uint8 Can_Controller_Id = 0u;
	Can_Hw_RegTypeRef Can_Reg = NULL_PTR;
	Can_PayloadType MB_Size = 0u;
	uint8 Max_MB_Buffer = 0u;

	for(Can_Controller_Id = 0u; Can_Controller_Id < CAN_MAX_CONTROLLERS; Can_Controller_Id++)
	{
		Can_Reg = (Can_Hw_RegTypeRef)Config->CanController[Can_Controller_Id].CanControllerBaseAddr;

		Can_Reg->MCR |= (uint32)(DRV_CAN_MCR_MDIS);           /* Module disable */
		Can_Reg->CTRL1 &= ~DRV_CAN_CTRL1_CLKSRC;;               /* Select peripheral clock for the CAN engine. */
		Can_Reg->MCR &= (uint32)(~(DRV_CAN_MCR_MDIS));        /* Module enable */

		Can_Reg->MCR |= DRV_CAN_MCR_SOFTRST;                    /* Soft Reset */
		while ((Can_Reg->MCR & DRV_CAN_MCR_SOFTRST) != 0u){};   /* Wait FlexCAN Reset */

		Can_Hw_EnterFreezeMode(Can_Reg);                        /* Enter Freeze mode */

		Can_Reg->CTRL1 = 0x0u;                                  /* Clean CTRL register */

		/* Automatic recovering from Bus Off state disabled. */
		Can_Reg->CTRL1 &= (~DRV_CAN_CTRL1_BOFFREC);

		/* Can Controller register configure. */
		Max_MB_Buffer = Config->CanController[Can_Controller_Id].CanControllerMaxMessageBuffer;

		/* DRV_CAN_MCR_SRXDIS Self reception disabled.                                  Written only in Freeze mode.
		 * DRV_CAN_MCR_IRMQ Individual Receive masking and queue feature are enabled.   Written only in Freeze mode.
		 * DRV_CAN_MCR_AEN Abort enabled.                                               Written only in Freeze mode.
		 * CanMessageBuffer -1u Set the maximum number of MBs. start from 0,so is max number-1. Written only in Freeze mode.
		 * */
		Can_Reg->MCR |= (DRV_CAN_MCR_SRXDIS + DRV_CAN_MCR_IRMQ + DRV_CAN_MCR_AEN + Max_MB_Buffer);

		/* DRV_CAN_CTRL1_LBUF Lowest number buffer is transmitted first.                Written only in Freeze mode. */
		Can_Reg->CTRL1 |= (DRV_CAN_CTRL1_LBUF);

		if(Config->CanController[Can_Controller_Id].CanBusoffProcessing == CAN_PROCESSING_POLLING)
		{
			/* DRV_CAN_CTRL1_BOFFMSK Bus Off interrupt disable. */
			Can_Reg->CTRL1 &= (~DRV_CAN_CTRL1_BOFFMSK);
		}
		else if(Config->CanController[Can_Controller_Id].CanBusoffProcessing == CAN_PROCESSING_INTERRUPT)
		{
			/* DRV_CAN_CTRL1_BOFFMSK Bus Off interrupt enable. */
			Can_Reg->CTRL1 |= DRV_CAN_CTRL1_BOFFMSK;
		}
		else
		{
			/* Do nothing */
		}

		/* The message error interrupt disable. */
		Can_Reg->CTRL1 &= ~DRV_CAN_CTRL1_ERRMSK;

		/* Warning Interrupt Disable            Written only in Freeze mode.*/
		Can_Reg->MCR &= ~DRV_CAN_MCR_WRNEN;

		/* DRV_CAN_CTRL2_ERRMSK_FAST ERRINT_FAST Error interrupt disabled.
		 * DRV_CAN_CTRL2_BOFFDONEMSK Bus Off Done interrupt disabled.
		 * */
		Can_Reg->CTRL2 &= ~(DRV_CAN_CTRL2_ERRMSK_FAST + DRV_CAN_CTRL2_BOFFDONEMSK);

		if(Config->CanController[Can_Controller_Id].CanFD_Support == FALSE)
		{
			/* Init CAN bit timing  */
			Can_Reg->CTRL1 &= 0x0000fff8u;                    /* Clean PSEG1 PSEG2 PRESDIV RJW */
			Can_Reg->CTRL1 |= (Config->CanController[Can_Controller_Id].CanControllerBaudrateConfig->CanControllerBaudRateReg);
		}
		else
		{
			Can_Reg->MCR |= DRV_CAN_MCR_FDEN;

			Can_Reg->CTRL2 |= DRV_CAN_CTRL2_ISOCANFDEN_MASK;

			MB_Size = Config->CanController[Can_Controller_Id].CanControllerPayload;
			/* Bit Rate Switch Enable.
			 * Set Message Buffer Data Size for Region 0 - 2 */
			Can_Reg->FDCTRL |=
					(DRV_CAN_FDCTRL_FDRATE | DRV_CAN_FDCTRL_MBDSR0(MB_Size) | DRV_CAN_FDCTRL_MBDSR1(MB_Size) | DRV_CAN_FDCTRL_MBDSR2(MB_Size));

			if(Config->CanController[Can_Controller_Id].CanControllerBaudrateConfig->CanControllerFdBaudrateConfig.CanControllerTDCEnable == TRUE)
			{
				Can_Reg->FDCTRL |= DRV_CAN_FDCTRL_TDCEN;
				Can_Reg->FDCTRL |=
					DRV_CAN_FDCTRL_TDCOFF(Config->CanController[Can_Controller_Id].CanControllerBaudrateConfig->CanControllerFdBaudrateConfig.CanControllerTrcvDelayCompensationOffset);
			}

			Can_Reg->CBT = DRV_CAN_CBT_BTF | Config->CanController[Can_Controller_Id].CanControllerBaudrateConfig->CanControllerBaudRateReg;

			Can_Reg->FDCBT = Config->CanController[Can_Controller_Id].CanControllerBaudrateConfig->CanControllerFdBaudrateConfig.CanControllerFdCbtRegister;
		}

		Can_Hw_Mb_Init(Can_Controller_Id, Config);

		Can_Reg->IFLAG1 = 0xffffffffu;       /* Clear  all Can_Mb interrupt flag */
		Can_Reg->IFLAG2 = 0xffffffffu;       /* Clear  all CAN_MB interrupt flag */
		Can_Reg->IFLAG3 = 0xffffffffu;       /* Clear  all CAN_MB interrupt flag */

		Can_Reg->MCR &= ~(DRV_CAN_MCR_SUPV); /* Exit Supervisor Mode */

		Can_Reg->MCR |= (uint32)(DRV_CAN_MCR_MDIS);
		/* Wait till enter low-power mode */
		while (((Can_Reg)->MCR & DRV_CAN_MCR_LPMACK) == 0u){};/* Module disable */

		Can_Hw_ExitFreezeMode(Can_Reg);        /* Exit Freeze Mode */
	}
}

/************************************************************************************/
/*
 * Brief                <This function performs Controller start Mode process>
 * Param-Name[in]       <Controller-CAN Controller enable interrupt>
 * Param-Name[out]      <None>
 * Param-Name[in/out]   <None>
 * Return               <None>
 * PreCondition         <None>
 * CallByAPI            <None>
 */
/***********************************************************************************/
void Can_Hw_StartMode(uint8 Controller)
{
	Can_Hw_RegTypeRef Can_Reg =
        (Can_Hw_RegTypeRef)Can_ConfigPtr->CanController[Controller].CanControllerBaseAddr;

	Can_Reg->ESR1 |= DRV_CAN_ESR1_BOFFINT;     /* Clean BUSOFF interrupt flag */
	Can_Reg->IFLAG1 = 0xffffffffu;             /* Clear the all MB interrupts */
	Can_Reg->IFLAG2 = 0xffffffffu;             /* Clear the all MB interrupts */
	Can_Reg->IFLAG3 = 0xffffffffu;             /* Clear the all MB interrupts */

	/* Enable the FlexCAN. */
	Can_Reg->MCR &= (uint32)(~(DRV_CAN_MCR_MDIS));
	/* Wait till exit low-power mode */
	while (((Can_Reg)->MCR & DRV_CAN_MCR_LPMACK) != 0u){};
}

/****************************************************************************
 * Brief               Cancel current TX message if not transmit.
 * Function Name :     Can_Cancel
 ****************************************************************************/
static void Can_Hw_Cancel(uint8 Controller , uint8 obj)
{
	Can_Hw_RegTypeRef Can_Reg = (Can_Hw_RegTypeRef)Can_ConfigPtr->CanController[Controller].CanControllerBaseAddr;;
	Can_Hw_MbTypeRef Can_Mb = Obtain_Mb_Addr(Controller, Can_Reg, obj);

 	do
 	{
        if(((Can_Reg->IFLAG1 >> obj) & 1u) == 1u)
        {
            Can_Reg->IFLAG1 = (1u << obj);
        }
        /* Writing of abort code (0b1001) into the CODE field */
        Can_Mb->CONFIG &= ~DRV_CAN_MB_CODE;
	    Can_Mb->CONFIG |= DRV_CAN_MB_ABORT_CODE;
        /* Check if the CAN_TX_ABORT is write into or not. */
    }
 	while((Can_Mb->CONFIG & DRV_CAN_MB_CODE) != DRV_CAN_MB_ABORT_CODE);
    /* Writing of TX_INACTIVE (0b1000) into the CODE field */
    Can_Mb->CONFIG &= ~DRV_CAN_MB_CODE;
    Can_Mb->CONFIG |= (CAN_TX_INACTIVE << 24u);

	Can_Reg->IFLAG1 = (1u << obj);
}
/************************************************************************************/
/*
 * Brief                <This function performs Controller stop Mode process>
 * Param-Name[in]       <Controller-CAN Controller enable interrupt>
 * Param-Name[out]      <None>
 * Param-Name[in/out]   <None>
 * Return               <None>
 * PreCondition         <None>
 * CallByAPI            <None>
 */
/***********************************************************************************/
void Can_Hw_StopMode(uint8 Controller)
{
	Can_Hw_RegTypeRef Can_Reg =
        (Can_Hw_RegTypeRef)Can_ConfigPtr->CanController[Controller].CanControllerBaseAddr;
    uint8 i = 0u;
    uint32 Can_HardwareObject_Index = 0u;
    uint8 Can_Controller_Mb_Index = 0u;

	/* Disable CAN module. */
	Can_Reg->MCR |= (uint32)(DRV_CAN_MCR_MDIS);
	/* Wait till enter low-power mode */
	while (((Can_Reg)->MCR & DRV_CAN_MCR_LPMACK) == 0u){};

	Can_Reg->IFLAG1 = 0xffffffffu;             /* Clear the all MB interrupts. */
	Can_Reg->IFLAG2 = 0xffffffffu;             /* Clear the all MB interrupts. */
	Can_Reg->IFLAG3 = 0xffffffffu;             /* Clear the all MB interrupts. */

	Can_Reg->ESR1 |= DRV_CAN_ESR1_BOFFINT;     /* Clean BUSOFF interrupt flag. */
	Can_Reg->ESR1 |= DRV_CAN_ESR1_BOFFDONEINT; /* Clean BUSOFF interrupt flag. */

	for(i = 0; i < Controller; i++)
	{
		Can_HardwareObject_Index += Can_ConfigPtr->CanController[i].CanControllerMaxCounter;
	}

	for(; Can_Controller_Mb_Index < Can_ConfigPtr->CanController[Controller].CanControllerMaxCounter; Can_Controller_Mb_Index++)
	{
		if(Can_ConfigPtr->Can_HardwareObject[Can_HardwareObject_Index].CanObjectType == CAN_OBJECT_TYPE_TRANSMIT)
		{
			/* CAN init TX Message Buffer */
			Can_Hw_Cancel(Controller, Can_Controller_Mb_Index);
		}
		Can_HardwareObject_Index++;
	}
}

/******************************************************************************/
/*
 * Brief               <This function performs Controller sleep Mode  process>
 * Param-Name[in]      <Controller- CAN Controller to be Mode process>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
/* req <CAN265> */
void Can_Hw_SleepMode(uint8 Controller)
{

}

/******************************************************************************/
/*
 * Brief               <This function performs Controller wakeup Mode  process>
 * Param-Name[in]      <Controller- CAN Controller to be Mode process>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
void Can_Hw_WakeUpMode(uint8 Controller)
{

}

void Can_Hw_Rx_Mb_Init
(
	uint8 Controller,
	uint8 Can_Controller_Mb_Index,
	uint32 Can_HardwareObject_Index,
	const Can_ConfigType* Config
)
{
	Can_Hw_RegTypeRef Can_Reg = (Can_Hw_RegTypeRef)Config->CanController[Controller].CanControllerBaseAddr;

	Can_Hw_Rx_Tx_Mb_Init(Controller, Can_Controller_Mb_Index, Can_HardwareObject_Index, Config, RX);

	if(Can_Controller_Mb_Index <= 31u)
	{
		/* Set mb tx interrupt */
		if (CAN_PROCESSING_INTERRUPT == Config->CanController[Controller].CanRxProcessing)
		{
			Can_Reg->IMASK1 |= (1u << Can_Controller_Mb_Index);       /* Enable current MB interrupt */
		}
		else
		{
			Can_Reg->IMASK1 &= (~(1u << Can_Controller_Mb_Index));    /* Disable current MB interrupt */
		}

	}
	else if(Can_Controller_Mb_Index <= 63u)
	{
		/* Set mb tx interrupt */
		if (CAN_PROCESSING_INTERRUPT == Config->CanController[Controller].CanRxProcessing)
		{
			Can_Reg->IMASK2 |= (1u << (Can_Controller_Mb_Index - 32u));       /* Enable current MB interrupt */
		}
		else
		{
			Can_Reg->IMASK2 &= (~(1u << (Can_Controller_Mb_Index - 32u)));    /* Disable current MB interrupt */
		}
	}
	else if(Can_Controller_Mb_Index <= 95u)
	{
		/* Set mb tx interrupt */
		if (CAN_PROCESSING_INTERRUPT == Config->CanController[Controller].CanRxProcessing)
		{
			Can_Reg->IMASK3 |= (1u << (Can_Controller_Mb_Index - 64u));       /* Enable current MB interrupt */
		}
		else
		{
			Can_Reg->IMASK3 &= (~(1u << (Can_Controller_Mb_Index - 64u)));    /* Disable current MB interrupt */
		}
	}
	else
	{
		/* Do nothing */
	}
}

void Can_Hw_Tx_Mb_Init
(
	uint8 Controller,
	uint8 Can_Controller_Mb_Index,
	uint32 Can_HardwareObject_Index,
	const Can_ConfigType* Config
)
{
	Can_Hw_RegTypeRef Can_Reg = (Can_Hw_RegTypeRef)Config->CanController[Controller].CanControllerBaseAddr;

	Can_Hw_Rx_Tx_Mb_Init(Controller, Can_Controller_Mb_Index, Can_HardwareObject_Index, Config, TX);

	if(Can_Controller_Mb_Index <= 31u)
	{
		/* Set mb tx interrupt */
		if (CAN_PROCESSING_INTERRUPT == Config->CanController[Controller].CanTxProcessing)
		{
			Can_Reg->IMASK1 |= (1u << Can_Controller_Mb_Index);       /* Enable current MB interrupt */
		}
		else
		{
			Can_Reg->IMASK1 &= (~(1u << Can_Controller_Mb_Index));    /* Disable current MB interrupt */
		}
	}
	else if(Can_Controller_Mb_Index <= 63u)
	{
		/* Set mb tx interrupt */
		if (CAN_PROCESSING_INTERRUPT == Config->CanController[Controller].CanTxProcessing)
		{
			Can_Reg->IMASK2 |= (1u << (Can_Controller_Mb_Index - 32u));       /* Enable current MB interrupt */
		}
		else
		{
			Can_Reg->IMASK2 &= (~(1u << (Can_Controller_Mb_Index - 32u)));    /* Disable current MB interrupt */
		}
	}
	else if(Can_Controller_Mb_Index <= 95u)
	{
		/* Set mb tx interrupt */
		if (CAN_PROCESSING_INTERRUPT == Config->CanController[Controller].CanTxProcessing)
		{
			Can_Reg->IMASK3 |= (1u << (Can_Controller_Mb_Index - 64u));       /* Enable current MB interrupt */
		}
		else
		{
			Can_Reg->IMASK3 &= (~(1u << (Can_Controller_Mb_Index - 64u)));    /* Disable current MB interrupt */
		}
	}
	else
	{
		/* Do nothing */
	}
    /* Clean Individual Mask Registers */
	Can_Reg->RXIMR[Can_Controller_Mb_Index] = 0u;
}
static void Can_Hw_Mb_Clean(uint8 Controller)
{
	uint8 Can_Controller_Mb_Index = 0u;
	Can_Hw_RegTypeRef Can_Reg = (Can_Hw_RegTypeRef)Can_ConfigPtr->CanController[Controller].CanControllerBaseAddr;
	Can_Hw_MbTypeRef Can_Mb;
	uint8 Msg_Code = 0xffu;

	for(Can_Controller_Mb_Index = 0u; Can_Controller_Mb_Index < Can_ConfigPtr->CanController[Controller].CanControllerMaxMessageBuffer; Can_Controller_Mb_Index++)
	{
		Can_Mb = (Can_Hw_MbTypeRef)Obtain_Mb_Addr(Controller, Can_Reg, Can_Controller_Mb_Index);

		Can_Mb->CONFIG &= (~(Msg_Code << 24u));
	}
}

void Can_Hw_Mb_Init(uint8 Controller, const Can_ConfigType* Config)
{
	uint8 Can_Controller_Mb_Index = 0u;
    uint32 Can_HardwareObject_Index = 0u;
    uint8 i = 0u;

	for(i = 0; i < Controller; i++)
	{
		Can_HardwareObject_Index += Can_ConfigPtr->CanController[i].CanControllerMaxCounter;
	}

    Can_Hw_Mb_Clean(Controller);
	for(; Can_Controller_Mb_Index < Can_ConfigPtr->CanController[Controller].CanControllerMaxCounter; Can_Controller_Mb_Index++)
	{
		if(Config->Can_HardwareObject[Can_HardwareObject_Index].CanObjectType == CAN_OBJECT_TYPE_RECEIVE)
		{
			/* CAN init RX Message Buffer */
			Can_Hw_Rx_Mb_Init(Controller, Can_Controller_Mb_Index, Can_HardwareObject_Index, Config);
		}
		else if(Config->Can_HardwareObject[Can_HardwareObject_Index].CanObjectType == CAN_OBJECT_TYPE_TRANSMIT)
		{
			/* CAN init TX Message Buffer */
			Can_Hw_Tx_Mb_Init(Controller, Can_Controller_Mb_Index, Can_HardwareObject_Index, Config);
		}
		else
		{
			/* Do nothing */
		}
		Can_HardwareObject_Index++;
	}
}

/************************************************************************************/
/*
 * Brief                <This function performs Transmission Data Handle>
 * Param-Name[in]       <Controller - Can Controller to be Tx process>
 * Param-Name[in]       <MBNumber - Can Controller messagebox number>
 * Param-Name[in]       <PduInfo - Can Controller read data buffer>
 * Param-Name[out]      <None>
 * Param-Name[in/out]   <None>
 * Return               <None>
 * PreCondition         <None>
 * CallByAPI            <None>
 */
/***********************************************************************************/
void Can_Hw_Write_Mb
(
	uint8 Controller,
	uint8 Hw_MB_Id,
	const Can_PduType* PduInfo
)
{
	uint8 i;
	uint8 Msg_Code = 0u;
	Can_Hw_MbTypeRef Can_Mb = NULL_PTR;
	uint8 *Data_Ptr = NULL_PTR;
	Can_Hw_RegTypeRef Can_Reg =
        (Can_Hw_RegTypeRef)Can_ConfigPtr->CanController[Controller].CanControllerBaseAddr;
	uint32 Mb_Config = 0;

	Can_Mb = Obtain_Mb_Addr(Controller, Can_Reg, Hw_MB_Id);

	Mb_Config = Can_Mb->CONFIG;

	if(Can_ConfigPtr->CanController[Controller].CanFD_Support == TRUE)
	{
		Mb_Config |= DRV_CAN_MB_EDL;
	}

	/* ID [28-0] Clear */
	Can_Mb->ID &= (~(0x1FFFFFFFu));

	if((Can_Mb->CONFIG & DRV_CAN_MB_IDE) == DRV_CAN_MB_IDE)
	{
		/* ID[28-0] */
	    Can_Mb->ID |= ((PduInfo->id) & 0x1FFFFFFFu);
	}
	else
	{
		/* ID[28-18] */
	    Can_Mb->ID |= (((PduInfo->id) & 0x7ffu) << 18u);
	}

	Data_Ptr = Can_Mb->DATA;

	/* Copy user's buffer into the message buffer data area. */
	for (i = 0u; i < PduInfo->length; i++)
	{
		(*Data_Ptr++) = PduInfo->sdu[i];
	}
	/* Padding 0 */
	for (i = PduInfo->length; i < Can_Hw_ComputeDLCValue(PduInfo); i++)
	{
		(*Data_Ptr++) = 0u;
	}

	/* Set the length of data in bytes.
	 * Set MB CODE. */
	Msg_Code = CAN_TX_DATA;

	Can_Mb->CONFIG = ((Mb_Config&(~(DRV_CAN_MB_CODE + DRV_CAN_MB_DLC)))|((Can_Hw_ComputeDLCValue(PduInfo) << 16u) + (Msg_Code << 24u)));

	/* Save pdu handle */
	CanControllerStatus[Controller].TxPduHandles[Hw_MB_Id] = PduInfo->swPduHandle;
}


void Can_HW_SetBaudrate(uint8 Controller, uint8 BaudRateConfigID)
{
	Can_Hw_RegTypeRef Can_Reg =
	            (Can_Hw_RegTypeRef)Can_ConfigPtr->CanController[Controller].CanControllerBaseAddr;
	Can_PayloadType MB_Size = Can_ConfigPtr->CanController[Controller].CanControllerPayload;

	Can_Hw_EnterFreezeMode(Can_Reg);

	if(Can_ConfigPtr->CanController[Controller].CanFD_Support == FALSE)
	{
		/* Init CAN bit timing  */
		Can_Reg->CTRL1 &= 0x0000fff8u;                    /* Clean PSEG1 PSEG2 PRESDIV RJW */
		Can_Reg->CTRL1 |= (Can_ConfigPtr->CanController[Controller].CanControllerBaudrateConfig[BaudRateConfigID].CanControllerBaudRateReg);
	}
	else
	{
		Can_Reg->MCR |= DRV_CAN_MCR_FDEN;

		Can_Reg->CTRL2 |= DRV_CAN_CTRL2_ISOCANFDEN_MASK;

		MB_Size = Can_ConfigPtr->CanController[Controller].CanControllerPayload;
		/* Bit Rate Switch Enable.
		 * Set Message Buffer Data Size for Region 0 - 2 */
		Can_Reg->FDCTRL |=
				(DRV_CAN_FDCTRL_FDRATE | DRV_CAN_FDCTRL_MBDSR0(MB_Size) | DRV_CAN_FDCTRL_MBDSR1(MB_Size) | DRV_CAN_FDCTRL_MBDSR2(MB_Size));

		if(Can_ConfigPtr->CanController[Controller].CanControllerBaudrateConfig[BaudRateConfigID].CanControllerFdBaudrateConfig.CanControllerTDCEnable == TRUE)
		{
			Can_Reg->FDCTRL |= DRV_CAN_FDCTRL_TDCEN;
			Can_Reg->FDCTRL |=
				DRV_CAN_FDCTRL_TDCOFF(Can_ConfigPtr->CanController[Controller].CanControllerBaudrateConfig[BaudRateConfigID].CanControllerFdBaudrateConfig.CanControllerTrcvDelayCompensationOffset);
		}

		Can_Reg->CBT = DRV_CAN_CBT_BTF | Can_ConfigPtr->CanController[Controller].CanControllerBaudrateConfig[BaudRateConfigID].CanControllerBaudRateReg;

		Can_Reg->FDCBT = Can_ConfigPtr->CanController[Controller].CanControllerBaudrateConfig[BaudRateConfigID].CanControllerFdBaudrateConfig.CanControllerFdCbtRegister;
	}

	Can_Hw_ExitFreezeMode(Can_Reg);
}

/************************************************************************************/
/*
 * Brief                <This function performs receive read Data Handle>
 * Param-Name[in]       <Controller - Can Controller to be Rx process>
 * Param-Name[in]       <Hw_MB_Id - Can Controller messagebox number>
 * Param-Name[in]       <PduInfo - Can Controller read data buffer>
 * Param-Name[out]      <None>
 * Param-Name[in/out]   <None>
 * Return               <None>
 * PreCondition         <None>
 * CallByAPI            <None>
 */
/***********************************************************************************/
extern void Can_Hw_Get_MB_Info(uint8 Controller, uint8 Hw_MB_Id, Can_PduType* PduInfo)
{
	uint8 i = 0;
	uint8 *Data_Ptr = NULL_PTR;
	Can_Hw_RegTypeRef Can_Reg =
			(Can_Hw_RegTypeRef)Can_ConfigPtr->CanController[Controller].CanControllerBaseAddr;
	Can_Hw_MbTypeRef Can_Mb = Obtain_Mb_Addr(Controller, Can_Reg, Hw_MB_Id);

	/* ID */
	if ((((Can_Mb->CONFIG) & (DRV_CAN_MB_IDE)) >> 21u) != 0u)  /* extended frame */
	{
		PduInfo->id = Can_Mb->ID;
		PduInfo->id |= 0x80000000u;   /* CanIf need extended Canid set 31 bit */
	}
	else /* Standard frame */
	{
		PduInfo->id = (Can_Mb->ID >> 18u);
	}
	if (((Can_Mb->CONFIG) & (DRV_CAN_MB_EDL)) == DRV_CAN_MB_EDL)  /* CAN-FD frame */
	{
		PduInfo->id |= 0x40000000u;   /* CAN-FD Canid set 30 bit */
	}

	/* DLC */
	PduInfo->length = Can_Hw_ComputeLengthValue((uint8)(((Can_Mb->CONFIG) & (DRV_CAN_MB_DLC)) >> 16u));

	Data_Ptr = Can_Mb->DATA;
	/* SDU */
	for (i = 0u; i < PduInfo->length; i++) /* req <CAN299> */
	{
		PduInfo->sdu[i] = (*Data_Ptr++);
	}

	Can_Mb->CONFIG &= ~DRV_CAN_MB_CODE;
	Can_Mb->CONFIG |= (CAN_RX_EMPTY << 24u);
}


#if (STD_ON == CAN_RX_POLLING)

static uint16 Obtain_Rx_Start_Mb(uint8 Controller)
{
	uint16 Rx_Mb_Start = 0u;

	if(Controller == 0u)
	{
		Rx_Mb_Start = Can_ConfigPtr->CanController[Controller].CanRxStart;
	}
	else
	{
		Rx_Mb_Start = Can_ConfigPtr->CanController[Controller].CanRxStart - Can_ConfigPtr->CanController[Controller].CanControllerMaxCounter;
	}

    return Rx_Mb_Start;
}
static uint16 Obtain_Rx_End_Mb(uint8 Controller)
{
	uint16 Rx_Mb_End = 0u;
	if(Controller == 0u)
	{
		Rx_Mb_End = Can_ConfigPtr->CanController[Controller].CanRxEnd;
	}
	else
	{
		Rx_Mb_End = Can_ConfigPtr->CanController[Controller].CanRxEnd - Can_ConfigPtr->CanController[Controller].CanControllerMaxCounter;
	}

	return Rx_Mb_End;
}

static void Can_Hw_Polling_Rx2CanIf
(
	uint8 Controller,
	Can_Hw_MbTypeRef Can_Mb,
	uint8 Mb_Index,
	uint16 Used_Max_Mb,
	Can_PduType Pdu
)
{

    PduInfoType PduInfo;
	Can_HwType Mailbox;
	Can_Hw_RegTypeRef Can_Reg =
			(Can_Hw_RegTypeRef)Can_ConfigPtr->CanController[Controller].CanControllerBaseAddr;

	PduInfo.SduDataPtr = Pdu.sdu;
	PduInfo.SduLength = Pdu.length;
	Mailbox.CanId = Pdu.id;
	Mailbox.ControllerId = Controller;
	Mailbox.Hoh = (Can_HwHandleType)(Mb_Index + Used_Max_Mb);
	CanIf_RxIndication(&Mailbox, &PduInfo);

	Can_Reg->IFLAG1 |=  (1u << Mb_Index);
	Can_Mb->CONFIG &= DRV_CAN_MB_CODE;
	Can_Mb->CONFIG |= (CAN_RX_EMPTY << 24u);
}

void Can_Hw_Polling_RxProcess(uint8 Controller)
{
	uint8 Mb_Index = 0u;
	Can_Hw_RegTypeRef Can_Reg =
			(Can_Hw_RegTypeRef)Can_ConfigPtr->CanController[Controller].CanControllerBaseAddr;
	Can_Hw_MbTypeRef Can_Mb = NULL_PTR;
	uint16 Rx_Mb_Start = 0u;
	uint16 Rx_Mb_End = 0u;
    uint32 iflag1_Status = 0u;
    uint32 iflag2_Status = 0u;
    uint32 iflag3_Status = 0u;
    uint8 RxData[64u] = {0u};
    Can_PduType Pdu;

	uint16 Used_Max_Mb = 0u;
	uint8 i = 0u;

    Pdu.sdu = RxData;

	for(i = 0u; i < Controller; i++)
	{
		Used_Max_Mb += Can_ConfigPtr->CanController[i].CanControllerMaxCounter;
	}

	Rx_Mb_Start = Obtain_Rx_Start_Mb(Controller);
	Rx_Mb_End = Obtain_Rx_End_Mb(Controller);

    if(Rx_Mb_End < 32u)
    {
    	if(Can_Reg->IFLAG1 != 0u)
		{

    		iflag1_Status = Can_Reg->IFLAG1;
            for(Mb_Index = Rx_Mb_Start; Mb_Index <= Rx_Mb_End; Mb_Index++)
            {
            	Can_Mb = Obtain_Mb_Addr(Controller, Can_Reg, Mb_Index);

            	if(((iflag1_Status >> Mb_Index) & 1u) == 1u)
            	{
            		Can_Hw_Get_MB_Info(Controller, Mb_Index, &Pdu);
            		Can_Hw_Polling_Rx2CanIf(Controller, Can_Mb, Mb_Index, Used_Max_Mb, Pdu);
            	}
            }
		}
    }
    else if(Rx_Mb_End < 64u)
    {
    	if(Can_Reg->IFLAG2 != 0u)
		{
			iflag2_Status = Can_Reg->IFLAG2;
			for(Mb_Index = Rx_Mb_Start - 32u; Mb_Index <= Rx_Mb_End - 32u; Mb_Index++)
			{
				Can_Mb = Obtain_Mb_Addr(Controller, Can_Reg, (Mb_Index + 32u));
				if(((iflag2_Status >> Mb_Index) & 1u) == 1u)
				{
            		Can_Hw_Polling_Get_MBInfo(Controller, Mb_Index, &Pdu);
					Can_Hw_Get_MB_Info(Controller, Mb_Index, &Pdu);

					Can_Hw_Polling_Rx2CanIf(Controller, Can_Mb, Mb_Index, Used_Max_Mb, Pdu);
				}
			}
		}
    }
    else if(Rx_Mb_End < 96u)
	{
    	if(Can_Reg->IFLAG3 != 0u)
		{
			iflag3_Status = Can_Reg->IFLAG3;
			for(Mb_Index = Rx_Mb_Start - 64u; Mb_Index <= Rx_Mb_End - 64u; Mb_Index++)
			{
				Can_Mb = Obtain_Mb_Addr(Controller, Can_Reg, (Mb_Index + 64u));
				if(((iflag3_Status >> Mb_Index) & 1u) == 1u)
				{
            		Can_Hw_Polling_Get_MBInfo(Controller, Mb_Index, &Pdu);
					Can_Hw_Get_MB_Info(Controller, Mb_Index, &Pdu);

					Can_Hw_Polling_Rx2CanIf(Controller, Can_Mb, Mb_Index, Used_Max_Mb, Pdu);
				}
			}
		}
	}
    else
    {
        /* Do Nothing */
    }
}
#endif

#if (STD_ON == CAN_TX_POLLING)
static uint16 Obtain_Tx_Start_Mb(uint8 Controller)
{
	uint16 Tx_Mb_Start = 0u;

	if(Controller == 0u)
	{
		Tx_Mb_Start = Can_ConfigPtr->CanController[Controller].CanTxStart;
	}
	else
	{
		Tx_Mb_Start = Can_ConfigPtr->CanController[Controller].CanTxStart - Can_ConfigPtr->CanController[Controller].CanControllerMaxCounter;
	}

    return Tx_Mb_Start;
}
static uint16 Obtain_Tx_End_Mb(uint8 Controller)
{
	uint16 Tx_Mb_End = 0u;
	if(Controller == 0u)
	{
		Tx_Mb_End = Can_ConfigPtr->CanController[Controller].CanTxEnd;
	}
	else
	{
		Tx_Mb_End = Can_ConfigPtr->CanController[Controller].CanTxEnd - Can_ConfigPtr->CanController[Controller].CanControllerMaxCounter;
	}

	return Tx_Mb_End;
}

static void Can_Hw_Polling_TxCleanCode(uint8 Controller, Can_Hw_MbTypeRef Can_Mb)
{
	Can_Mb->CONFIG &= DRV_CAN_MB_CODE;
	Can_Mb->CONFIG |= (CAN_TX_INACTIVE << 24u);
	if(Can_ConfigPtr->CanController[Controller].CanControllerBaudrateConfig->CanControllerFdBaudrateConfig.CanControllerTxBitRateSwitch == TRUE)
	{
		/* BRS = 1: Bit Rate Switch enabled */
		Can_Mb->CONFIG |= DRV_CAN_MB_BRS;
	}
	else
	{
		/* BRS = 1: Bit Rate Switch enabled */
		Can_Mb->CONFIG &= (~DRV_CAN_MB_BRS);
	}
}

void Can_Hw_Polling_TxProcess(uint8 Controller)
{
	uint8 Mb_Index = 0u;
	Can_Hw_RegTypeRef Can_Reg =
			(Can_Hw_RegTypeRef)Can_ConfigPtr->CanController[Controller].CanControllerBaseAddr;
	Can_Hw_MbTypeRef Can_Mb = NULL_PTR;
	uint16 Tx_Mb_Start = 0u;
	uint16 Tx_Mb_End = 0u;
	uint32 iflag1_Status = 0u;
	uint32 iflag2_Status = 0u;
	uint32 iflag3_Status = 0u;

	uint16 Used_Max_Mb = 0u;
	uint8 i = 0u;

	for(i = 0u; i < Controller; i++)
	{
		Used_Max_Mb += Can_ConfigPtr->CanController[i].CanControllerMaxCounter;
	}

	Tx_Mb_Start = Obtain_Tx_Start_Mb(Controller);
	Tx_Mb_End = Obtain_Tx_End_Mb(Controller);

    if(Tx_Mb_End < 32u)
    {
    	if(Can_Reg->IFLAG1 != 0u)
		{
    		iflag1_Status = Can_Reg->IFLAG1;
            for(Mb_Index = Tx_Mb_Start; Mb_Index <= Tx_Mb_End; Mb_Index++)
            {
            	Can_Mb = Obtain_Mb_Addr(Controller, Can_Reg, Mb_Index);

            	if(((iflag1_Status >> Mb_Index) & 1u) == 1u)
            	{
                    CanIf_TxConfirmation(CanControllerStatus[Controller].TxPduHandles[Mb_Index + Used_Max_Mb]);

                    Can_Reg->IFLAG1 |=  (1u << Mb_Index);
                    Can_Hw_Polling_TxCleanCode(Controller, Can_Mb);
            	}
            }
		}
    }
    else if(Tx_Mb_End < 64u)
    {
    	if(Can_Reg->IFLAG2 != 0u)
		{
			iflag2_Status = Can_Reg->IFLAG2;
			for(Mb_Index = Tx_Mb_Start - 32u; Mb_Index <= Tx_Mb_End - 32u; Mb_Index++)
			{
				Can_Mb = Obtain_Mb_Addr(Controller, Can_Reg, (Mb_Index + 32u));
				if(((iflag2_Status >> Mb_Index) & 1u) == 1u)
				{
					CanIf_TxConfirmation(CanControllerStatus[Controller].TxPduHandles[Mb_Index + Used_Max_Mb]);

					Can_Reg->IFLAG2 |=  (1u << Mb_Index);
					Can_Hw_Polling_TxCleanCode(Controller, Can_Mb);
				}
			}
		}
    }
    else if(Tx_Mb_End < 96u)
	{
    	if(Can_Reg->IFLAG3 != 0u)
		{
			iflag3_Status = Can_Reg->IFLAG3;
			for(Mb_Index = Tx_Mb_Start - 64u; Mb_Index <= Tx_Mb_End - 64u; Mb_Index++)
			{
				Can_Mb = Obtain_Mb_Addr(Controller, Can_Reg, (Mb_Index + 64u));
				if(((iflag3_Status >> Mb_Index) & 1u) == 1u)
				{
					CanIf_TxConfirmation(CanControllerStatus[Controller].TxPduHandles[Mb_Index + Used_Max_Mb]);

					Can_Reg->IFLAG3 |=  (1u << Mb_Index);
					Can_Hw_Polling_TxCleanCode(Controller, Can_Mb);
				}
			}
		}
	}
    else
    {

    }
}
#endif

#if (STD_ON == CAN_BUSOFF_POLLING)
void Can_Hw_Polling_BusOffProcess(uint8 Controller)
{
	Can_Hw_RegTypeRef Can_Reg =
			(Can_Hw_RegTypeRef)Can_ConfigPtr->CanController[Controller].CanControllerBaseAddr;
	Can_ReturnType ret;
	if((Can_Reg->ESR1 & DRV_CAN_ESR1_BOFFINT) == DRV_CAN_ESR1_BOFFINT)
	{
		ret = Can_StopMode(Controller);

		if(CAN_OK == ret)
		{
			CanIf_ControllerBusOff(Controller);
		}
	}
}
#endif

#if (STD_ON == CAN_WAKEUP_POLLING)
void Can_Hw_Polling_WakeUpProcess(uint8 Controller)
{
		EcuM_WakeupSourceType WakeupSourceId = ECUM_WKSOURCE_EXTERNAL_IO;
		Can_Hw_StopMode(Controller);
		CanControllerStatus[Controller].CntrlMode = CAN_T_STOP;
		CanControllerStatus[Controller].WakeupStatus = TRUE;

		EcuM_CheckWakeup(WakeupSourceId);
}
#endif


